package org.inh.ld20.dangerousbrother;

import java.awt.Graphics;
import java.util.Vector;

import org.inh.ld20.dangerousbrother.entity.Entity;
import org.inh.ld20.dangerousbrother.entity.Entity.FacingDirection;

/**
 * Used mainly for collision detection, also controls the screen position
 * and loading of the level data file. You know, level stuff.
 *
 */
public class Level {
	public static final int TILE_SIZE = 32;
	
	public Vector<Entity> entities;
	private int[] tiles;
	private Camera camera;
	
	public Level(Camera c) {
		entities = new Vector<Entity>(64);
		this.camera = c;
		
		// Load the level from Art.level
		tiles = Art.level.getRGB(0, 0, Art.level.getWidth(), Art.level.getHeight(), null, 0, Art.level.getWidth());
	}
	
	public void tick(Input input) {
		Entity mainCharacter = entities.get(0);
		
		// apply gravity
		if(input.buttons[Input.JUMP] && !input.oldButtons[Input.JUMP]) {
			mainCharacter.attemptJump();
		}
		
		for(Entity e : entities) {
			e.gravity(this);
			e.animation.tick();
			
			if(e.following != null) {
				if(e.following.y+e.following.height <= e.y) {
					e.attemptJump();
				}
				double destX = e.following.x + e.width*e.following.facingDirection.singularValue;
				
				double xmove = destX - e.x;
				if(xmove > 1.0) xmove = 1.0;
				if(xmove < -1.0) xmove = -1.0;
				if(xmove != 0.0)
					e.tryMove(this, xmove, 0);
				
				double xdiff = (e.following.x + e.following.width/2.0) - (e.x + e.width/2.0);
				if(xdiff > 0)
					e.facingDirection = FacingDirection.RIGHT;
				else if(xdiff < 0)
					e.facingDirection = FacingDirection.LEFT;
			}
		}
	}
	
	public void draw(Graphics g) {
		final Camera c = this.camera;
		for(int x=(int) Math.floor(c.x); x < Math.ceil(c.x + (DangerousBrother.GAME_WIDTH / TILE_SIZE)); x++) {
			for(int y=(int) Math.floor(c.y); y < Math.ceil(c.y + (DangerousBrother.GAME_HEIGHT / TILE_SIZE)); y++) {
				int tileIdx = y*Art.level.getWidth()+x;
				if(tileIdx < 0 || tileIdx >= tiles.length)
					tileIdx = 0;
				int tileDrawX = (int) ((x-c.x)*TILE_SIZE);
				int tileDrawY = (int) ((y-c.y)*TILE_SIZE);
				
				switch(tiles[tileIdx]) {
				case 0xFFFFFFFF:
				case 0xFFF8F8F8:
					// draw background image
					g.drawImage(Art.tile_sky, tileDrawX, tileDrawY, tileDrawX+TILE_SIZE, tileDrawY+TILE_SIZE, 0, 0, Art.tile_sky.getWidth(), Art.tile_sky.getHeight(), null);
					break;
				case 0xFF603913:
					// draw ground
					g.drawImage(Art.tile_underground, tileDrawX, tileDrawY, tileDrawX+TILE_SIZE, tileDrawY+TILE_SIZE, 0, 0, Art.tile_underground.getWidth(), Art.tile_underground.getHeight(), null);
					break;
				case 0xFF00A651:
					// draw grass
					g.drawImage(Art.tile_grass, tileDrawX, tileDrawY, tileDrawX+TILE_SIZE, tileDrawY+TILE_SIZE, 0, 0, Art.tile_grass.getWidth(), Art.tile_grass.getHeight(), null);
					break;
				default:
					// draw something for an invalid pixel
				}
			}
		}
	}
	
	public boolean canBeLocated(Entity obj, double newx, double newy) {
		if(obj == null) throw new RuntimeException("canBeLocated: obj == null");
		for(Entity e : entities) {
			if(e == null || obj == e || obj.followedBy(e) || e.followedBy(obj)) continue;
			
			if(newx > e.x+e.width ||
					newy > e.y+e.height ||
					e.x > newx+obj.width ||
					e.y > newy+obj.height) {
				// no collision
			} else {
				return false;
			}
				
		}
		
		// TODO also check for terrain collision
		
		return true;
	}
}
